/*************************************************************************  
 *   This file is part of UBBMPSREADER.
 *
 *   UBBMPSREADER is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   UBBMPSREADER is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with UBBMPSREADER.  If not, see <http://www.gnu.org/licenses/>. 
 *************************************************************************/

package cs.ubbcluj.ro.datatypes.implementations;

import cs.ubbcluj.ro.datatypes.interfaces.*;

public abstract strictfp class AbstractVector implements Vector {
	
    public void set(Vector v) {
		for (int i = 0; i < v.getNrOfRows(); i++) {
		    addElement(i, v.get(i));
		}
    }

    public double min() {
		double minim = get(0);
		for (int i = 1; i < getNrOfRows(); i++) {			
		    if (get(i) < minim) {
		    	minim = get(i);		    	
		    }
		}
		return minim;
    }
    
    public double max() {
    	return infinityNorm();
    }
    
    public double infinityNorm() {
		double maxim = get(0);
		for (int i = 1; i < getNrOfRows(); i++) {
		    if (get(i) > maxim)
		    	maxim = get(i);
		}
		return maxim;
    }

    public void round() {
		double value;
		for (int i = 0; i < getNrOfRows(); i++) {
		    value = 100 * get(i);
		    value = Math.round(value);
		    value /= 100;
		    addElement(i, value);
		}
    }
    
    public double norm() {
    	double sqrSum = 0.0;
    	double value = 0.0;
		for (int i = 0; i < getNrOfRows(); i++) {
			value = get(i);
			sqrSum += value * value;
		}    			
    	return Math.sqrt(sqrSum);
    }
	
    public Vector sum(Vector v) throws InterruptedException {
		if (getNrOfRows() != v.getNrOfRows())
		    throw new InterruptedException("The given vectors have different sizes!");
		else {
		    for (int i = 0; i < getNrOfNonZeros(); i++)
			addElement(i, get(i) + v.get(i));
		    return this;
		}
    }
    
    public Vector sum(double value) throws InterruptedException {
    	for (int i = 0; i < getNrOfNonZeros(); i++)
    		addElement(i, get(i) + value);
		return this;
    }
    
    public double sumOfComponents() {
    	double sum = 0.0;
    	for (int i = 0; i < getNrOfNonZeros(); i++)
    		sum += get(i);    		
		return sum;
    }
    
    public Vector productScalar(int i, double d) {
    	addElement(i, get(i) * d);
    	return this;
    }
    
    public Vector productScalar(Vector v) {
		for (int i = 0; i < v.getNrOfRows(); i++) {
			this.productScalar(i, v.get(i));
		}
		return this;
    }
    
    public double product(Vector v) throws InterruptedException {
		if (getNrOfRows() != v.getNrOfRows()){ 
			throw new InterruptedException("The given vectors have different sizes!");
		} else {
		    double product = 0;
		    for (int i = 0; i < getNrOfRows(); i++)
			product += get(i) * v.get(i);
		    return product;
		}
    }
    
	public Vector product(Matrix m) throws InterruptedException {
		Vector result = createHelperVector(m.getNrOfColumns());
		
		if (getNrOfRows() != m.getNrOfRows()) {
		    throw new InterruptedException("The given vectors have different sizes!");
		} else {
		    double sum;
		    for (int i = 0; i < m.getNrOfColumns(); i++) {
			sum = 0;
			for (int j = 0; j < getNrOfRows(); j++) {
			    sum += get(j) * m.get(j, i);
			}
			result.set(i, sum);
		    }
		    return result;
		}
    }

    public Vector product(double n) {
		for (int i = 0; i < getNrOfRows(); i++)
		    addElement(i, get(i) * n);
		return this;
    }

    public Vector diff(Vector v) throws InterruptedException {
    	Vector helperVector = v.createHelperVector(v.getNrOfRows());
		if (getNrOfRows() != v.getNrOfRows())
		    throw new InterruptedException("The given vectors have different sizes!");
		else {
		    for (int i = 0; i < getNrOfRows(); i++) {
		    	helperVector.set(i, get(i) - v.get(i));			    	
		    }		    		    
		    return helperVector;
		}
    }

    public Vector inv() {
    	Vector helperVector = this.createHelperVector(this.getNrOfRows());    	
		double ertek;
		for (int i = 0; i < getNrOfRows(); i++) {
		    ertek = get(i);
		    if (ertek != 0)
			helperVector.addElement(i, 1 / ertek);
		}
		return helperVector;
    }
    
    public Vector sqrt() throws InterruptedException {    	
	    for (int i = 0; i < getNrOfRows(); i++) {
	    	this.set(i, Math.sqrt(this.get(i)));	    	
	    }	    	    
	    return this;		
    }
    
    public void print() {
    	for (int i = 0; i < getNrOfRows(); i++) {    		
			System.out.println(get(i));
    	}
    }
}